package com.sky.controller.admin;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.entity.Category;
import com.sky.entity.Setmeal;
import com.sky.entity.SetmealDish;
import com.sky.result.Result;
import com.sky.service.CategoryService;
import com.sky.service.SetmealDishService;
import com.sky.service.SetmealService;
import com.sky.vo.SetmealVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 套餐管理
 */
@RestController
@RequestMapping("/admin/setmeal")
@Api(tags = "套餐相关接口")
@Slf4j
public class SetmealController {
    @Autowired
    SetmealService setmealService;
    @Autowired
    CategoryService categoryService;
    @Autowired
    SetmealDishService setmealDishService;

    /**
     * 根据查询条件分页获取套餐信息
     * 此方法通过接收一个包含查询条件的DTO对象，来实现对套餐数据的分页查询和条件过滤
     * 它根据类别ID、套餐名称和状态进行筛选，并按更新时间降序排列结果
     *
     * @param dto 包含分页和查询条件的DTO对象，用于指定查询参数
     * @return 返回一个包含分页查询结果的Result对象，其中每条记录都转换为SetmealVO对象，并附加了分类名称
     */
    @GetMapping("/page")
    @ApiOperation("套餐分页查询")
    public Result pageQuery(SetmealPageQueryDTO dto){
        // 创建分页对象，传入当前页码和每页大小
        Page<Setmeal> page = new Page<>(dto.getPage(), dto.getPageSize());

        // 构建查询条件，根据类别ID、套餐名称和状态进行筛选，并按更新时间降序排列结果
        setmealService.query()
                .eq(dto.getCategoryId()!=null,"category_id",dto.getCategoryId())
                .like(dto.getName()!=null,"name",dto.getName())
                .eq(dto.getStatus()!=null,"status",dto.getStatus())
                .orderByDesc("update_time")
                .page(page);

        // 将查询结果转换为SetmealVO对象，并附加分类名称
        page.convert(setmeal -> {
            SetmealVO setmealVO = BeanUtil.toBean(setmeal, SetmealVO.class);
            Category category = categoryService.getById(setmeal.getCategoryId());
            setmealVO.setCategoryName(category.getName());
            return setmealVO;
        });
        // 返回包含分页查询结果的Result对象
        return Result.success(page);
    }

    /**
     * 添加套餐信息
     *
     * @param dto 套餐DTO对象，包含套餐及其关联的菜品信息
     * @return 返回操作结果
     */
    @PostMapping
    @ApiOperation("添加套餐")
    @CacheEvict(cacheNames = "setmealCache", key = "#dto.categoryId")
    public Result add(@RequestBody SetmealDTO dto){
        // 将DTO对象转换为套餐对象
        Setmeal setmeal = BeanUtil.toBean(dto, Setmeal.class);
        // 设置套餐的创建时间和更新时间为当前时间
        setmeal.setCreateTime(LocalDateTime.now());
        setmeal.setUpdateTime(LocalDateTime.now());
        // 设置套餐状态为1，表示可用
        setmeal.setStatus(1);
        // 保存套餐信息到数据库
        setmealService.save(setmeal);

        // 获取套餐关联的菜品列表
        List<SetmealDish> setmealDishes= dto.getSetmealDishes();
        // 遍历菜品列表，为每个菜品设置套餐ID并保存
        setmealDishes.forEach(setmealDish -> {
            setmealDish.setSetmealId(setmeal.getId());
            setmealDishService.save(setmealDish);
        });

        // 返回成功操作结果
        return Result.success();
    }

    /**
     * 删除菜品
     *
     * 根据提供的菜品ID列表，批量删除菜品及其在套餐中的关联信息
     *
     * @param ids 要删除的菜品ID列表
     * @return 返回删除操作的结果，包括是否成功
     */
    @DeleteMapping
    @ApiOperation("批量删除套餐菜品")
    @CacheEvict(cacheNames = "setmealCache", allEntries = true)
    public Result deleteDish(@RequestParam List<Long> ids){
        // 批量删除菜品
        setmealService.removeBatchByIds(ids);
        // 更新套餐菜品关联信息，删除与提供的菜品ID列表相关的所有记录
        setmealDishService.update().in("dish_id", ids).remove();
        // 返回成功结果
        return Result.success();
    }

    /**
     * 根据ID获取套餐详细信息
     *
     * 此方法首先通过ID获取套餐（Setmeal）对象，然后查询与该套餐ID关联的所有套餐菜品（SetmealDish）列表
     * 最后，将套餐对象和其关联的菜品列表封装到一个套餐视图对象（SetmealVO）中，并返回成功结果
     *
     * @param id 套餐的唯一标识符
     * @return 返回包含套餐详细信息的结果对象
     */
    @GetMapping("/{id}")
    @ApiOperation("根据id查询套餐")
    public Result getById(@PathVariable Long id){
        // 根据ID获取套餐对象
        Setmeal setmeal = setmealService.getById(id);

        // 查询与套餐ID匹配的所有套餐菜品列表
        List<SetmealDish> setmealDishes = setmealDishService.query()
                .eq("setmeal_id", id)
                .list();

        // 将套餐对象转换为套餐视图对象
        SetmealVO setmealVO = BeanUtil.toBean(setmeal, SetmealVO.class);
        // 将套餐菜品列表设置到套餐视图对象中
        setmealVO.setSetmealDishes(setmealDishes);

        // 返回成功结果，包含套餐视图对象
        return Result.success(setmealVO);
    }

    @PutMapping
    @ApiOperation("修改套餐")
    @CacheEvict(cacheNames = "setmealCache", allEntries = true)
    public Result update(@RequestBody SetmealDTO dto){
        // 更新套餐信息
        Setmeal setmeal = BeanUtil.toBean(dto, Setmeal.class);
        setmealService.updateById(setmeal);

        //更新套餐与菜品的关联信息
        List<SetmealDish> setmealDishes = dto.getSetmealDishes();
        setmealDishService.update()
                        .eq("setmeal_id",dto.getId())
                        .remove();

        setmealDishes.forEach(setmealDish -> {
            setmealDish.setSetmealId(setmeal.getId());
            setmealDishService.save(setmealDish);
        });

        return Result.success();
    }

    @PostMapping("/status/{status}")
    @ApiOperation("起售停售套餐")
    @CacheEvict(cacheNames = "setmealCache", allEntries = true)
    public Result<Void> startOrStop(@PathVariable Integer status, Long id) {
        // 更新套餐的起售或停售状态
        setmealService.update()
                .eq("id", id)
                .set("status", status)
                .update();
        return Result.success();
    }

}